home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / WIN_VID / ALLPAPER.ZIP;1 / ALLPAPC.ZIP / ALLPAPER.C next >
Encoding:
C/C++ Source or Header  |  1994-02-01  |  42.6 KB  |  1,458 lines

  1. /*
  2.  *  AllPaper shrinks and expands Windows wallpaper files to fit screens of
  3.  *  any resolution.
  4.  */
  5.  
  6. #include <windows.h>
  7. #include <commdlg.h>
  8. #include <stdlib.h>
  9. #include <math.h>
  10. #include "allpaper.h"
  11.  
  12. #define LINEWIDTH(bits)         ((((bits) + 31) >> 5) << 2)
  13.  
  14. #define IO_BLOCK_SIZE           0x8000
  15. #define COUNTER_BASE            1000000
  16.  
  17. typedef struct {
  18.     HGLOBAL hBmi;       // Handle to global memory block containing BITMAPINFO
  19.     HGLOBAL hBits;      // Handle to global memory block containing bitmap bits
  20.     HPALETTE hPalette;  // Palette handle
  21. } DIB;
  22.  
  23. long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
  24. BOOL FAR PASCAL AboutDlgProc (HWND, WORD, WORD, LONG);
  25.  
  26. int ReadDib (HWND, char *szFileName, DIB *pDib);
  27. int StretchDibAndSave (char *szFileName, DIB *dib, LONG, LONG);
  28. void StretchBits (BYTE __huge *, int, int, BYTE __huge *, int, int, int);
  29. void StretchScanLine (BYTE __huge *, int, BYTE __huge *, int, int, UINT,
  30.                       DWORD);
  31. void CopyBits (BYTE __huge *, DWORD, BYTE __huge *, DWORD, int);
  32.  
  33. BOOL GetOpenName (HWND, char *, int);
  34. BOOL GetSaveName (HWND, char *, int);
  35. void InitGroupRect (HWND, int, RECT *, BOOL);
  36. void DrawGroupRect (HDC, RECT *);
  37. void CenterDialog (HWND);
  38. void SaveSettings (HWND);
  39. void InitProgram (HWND);
  40. void PositionWindow (HWND);
  41.  
  42. int nSize;                                      // Output size index
  43. LONG lWidth[5] = { 640, 800, 1024, 1280, 0 };   // Output width array
  44. LONG lHeight[5] = { 480, 600, 768, 1024, 0 };   // Output height array
  45.  
  46. RECT rectFrame;                 // Coordinates of frame surrounding bitmap
  47. RECT rectPicture;               // Coordinates where bitmap is displayed
  48. RECT rectControls;              // Coordinates of frame surrounding controls
  49. OPENFILENAME ofn;               // Structure for obtaining file names
  50.  
  51. char szIniFile[128];            // INI file name
  52. char szSection[] = "Settings";  // INI file section name
  53. char *szEntry[] = {             // INI file entry names
  54.     "WindowPos",
  55.     "OutputSize"
  56. };
  57.  
  58. char *szError[] = {
  59.     "Error",
  60.     "The file was not found or could not be opened",
  61.     "An error occurred while the file was being read",
  62.     "The end of the file was encountered unexpectedly",
  63.     "Unsupported file format (file does not contain a DIB)",
  64.     "Unsupported file format (DIB is compressed)",
  65.     "Insufficient memory",
  66.     "Error creating output file",
  67.     "An error occurred while the file was being written",
  68.     "Disk full error"
  69. };
  70.  
  71. char *szWarning[] = {
  72.     "Warning",
  73.     "The end of the file was encountered unexpectedly. This probably "\
  74.     "means there is an error in the bitmap which could prevent the image "\
  75.     "from displaying properly."
  76. };
  77.  
  78. char *szFilter[] = {
  79.     "BMP Files (*.BMP)", "*.BMP",
  80.     "All Files (*.*)", "*.*", ""
  81. };
  82.  
  83. /*
  84.  *  Function WinMain.
  85.  */
  86.  
  87. int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  88.                     LPSTR lpszCmdLine, int nCmdShow)
  89. {
  90.     static char szAppName[] = "AllPaper";
  91.     WNDCLASS wndclass;
  92.     HWND hwnd;
  93.     MSG msg;
  94.  
  95.     if (!hPrevInstance) {
  96.         wndclass.style = 0;
  97.         wndclass.lpfnWndProc = (WNDPROC) WndProc;
  98.         wndclass.cbClsExtra = 0;
  99.         wndclass.cbWndExtra = DLGWINDOWEXTRA;
  100.         wndclass.hInstance = hInstance;
  101.         wndclass.hIcon = LoadIcon (hInstance, szAppName);
  102.         wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
  103.         wndclass.hbrBackground = NULL;
  104.         wndclass.lpszMenuName = NULL;
  105.         wndclass.lpszClassName = szAppName;
  106.  
  107.         RegisterClass (&wndclass);
  108.     }
  109.  
  110.     hwnd = CreateDialog (hInstance, szAppName, 0, NULL);
  111.  
  112.     InitProgram (hwnd);
  113.  
  114.     ShowWindow (hwnd, nCmdShow == SW_SHOWMAXIMIZED ? SW_SHOW : nCmdShow);
  115.     UpdateWindow (hwnd);
  116.  
  117.     while (GetMessage (&msg, NULL, 0, 0))
  118.         if (!IsDialogMessage (hwnd, &msg))
  119.             DispatchMessage (&msg);
  120.  
  121.     return msg.wParam;
  122. }
  123.  
  124. /*
  125.  *  WndProc processes messages to the main window
  126.  */
  127.  
  128. long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  129. {
  130.     char szFileName[80];
  131.     char szHeader[_MAX_FNAME + _MAX_EXT + 16];
  132.     char szBuffer[8];
  133.  
  134.     static DIB dib;
  135.     static HBRUSH hPatternBrush;
  136.     static BOOL bDirty = FALSE;
  137.     static HINSTANCE hInstance;
  138.  
  139.     HDC hdc;
  140.     LPBITMAPINFOHEADER lpBmih;
  141.     FARPROC lpfnAboutDlgProc;
  142.     void FAR *lpBits;
  143.     HBITMAP hBitmap;
  144.     HCURSOR hCursor;
  145.     HMENU hSysMenu;
  146.     PAINTSTRUCT ps;
  147.     POINT point;
  148.     RECT rect;
  149.     int i;
  150.  
  151.     switch (message) {
  152.  
  153.     case WM_CREATE:
  154.         //
  155.         // Get ready!
  156.         //
  157.         hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
  158.         i = GetModuleFileName (hInstance, szIniFile, sizeof (szIniFile));
  159.         while (szIniFile[i--] != 0x2E);
  160.         lstrcpy (&szIniFile[i+2], "INI");
  161.  
  162.         hPatternBrush = CreatePatternBrush (hBitmap = LoadBitmap (hInstance,
  163.             "Background"));
  164.         DeleteObject (hBitmap);
  165.  
  166.         hSysMenu = GetSystemMenu (hwnd, FALSE);
  167.         DeleteMenu (hSysMenu, SC_SIZE, MF_BYCOMMAND);
  168.         DeleteMenu (hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  169.         AppendMenu (hSysMenu, MF_SEPARATOR, 0, NULL);
  170.         AppendMenu (hSysMenu, MF_STRING, IDM_ABOUT, "&About AllPaper...");
  171.  
  172.         PositionWindow (hwnd);
  173.         return 0;
  174.  
  175.     case WM_PAINT:
  176.         //
  177.         // Repaint the window.
  178.         //
  179.         hdc = BeginPaint (hwnd, &ps);
  180.         DrawGroupRect (hdc, &rectFrame);
  181.         DrawGroupRect (hdc, &rectControls);
  182.  
  183.         if (bDirty) {
  184.             hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  185.             SelectPalette (hdc, dib.hPalette, 0);
  186.             RealizePalette (hdc);
  187.  
  188.             lpBmih = (LPBITMAPINFOHEADER) GlobalLock (dib.hBmi);
  189.             lpBits = GlobalLock (dib.hBits);
  190.  
  191.             SetStretchBltMode (hdc, STRETCH_DELETESCANS);
  192.  
  193.             StretchDIBits (hdc, rectPicture.left, rectPicture.top,
  194.                 rectPicture.right - rectPicture.left,
  195.                 rectPicture.bottom - rectPicture.top, 0, 0,
  196.                 (int) lpBmih->biWidth, (int) lpBmih->biHeight,
  197.                 lpBits, (LPBITMAPINFO) lpBmih, DIB_RGB_COLORS, SRCCOPY);
  198.  
  199.             GlobalUnlock (dib.hBits);
  200.             GlobalUnlock (dib.hBmi);
  201.             SetCursor (hCursor);
  202.         }
  203.  
  204.         EndPaint (hwnd, &ps);
  205.         return 0;
  206.  
  207.     case WM_ERASEBKGND:
  208.         //
  209.         // Fill the window with the pattern stored in ALLPAPER.BMP.
  210.         //
  211.         GetClientRect (hwnd, &rect);
  212.         UnrealizeObject (hPatternBrush);
  213.         point.x = point.y = 0;
  214.         ClientToScreen (hwnd, &point);
  215.         SetBrushOrg ((HDC) wParam, point.x, point.y); 
  216.         FillRect ((HDC) wParam, &rect, hPatternBrush);
  217.         return 1;
  218.  
  219.     case WM_CTLCOLOR:
  220.         //
  221.         // Customize the control colors.
  222.         //
  223.         SetBkColor ((HDC) wParam, RGB (192, 192, 192));
  224.         return GetStockObject (LTGRAY_BRUSH);
  225.  
  226.     case WM_COMMAND:
  227.         switch (wParam) {
  228.  
  229.         case IDD_NEW:
  230.             //
  231.             // Load and display a new bitmap.
  232.             //
  233.             if (!GetOpenName (hwnd, szFileName, sizeof (szFileName)))
  234.                 return 0;
  235.  
  236.             if (bDirty) {
  237.                 GlobalFree (dib.hBmi);
  238.                 GlobalFree (dib.hBits);
  239.                 DeleteObject (dib.hPalette);
  240.             }
  241.  
  242.             hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  243.             i = ReadDib (hwnd, szFileName, &dib);
  244.             SetCursor (hCursor);
  245.  
  246.             if (i) {
  247.                 MessageBox (hwnd, szError[i], szError[0], MB_OK);
  248.                 SetDlgItemText (hwnd, IDD_HEADER, "");
  249.                 bDirty = FALSE;
  250.                 EnableWindow (GetDlgItem (hwnd, IDD_SAVE), FALSE);
  251.                 InvalidateRect (hwnd, &rectPicture, FALSE);
  252.                 return 0;
  253.             }
  254.  
  255.             _splitpath (szFileName, NULL, NULL, szHeader, szBuffer);
  256.             lstrcat (szHeader, szBuffer);
  257.             lpBmih = (LPBITMAPINFOHEADER) GlobalLock (dib.hBmi);
  258.             wsprintf (&szHeader[lstrlen (szHeader)], " (%u x %u)",
  259.                 (unsigned) lpBmih->biWidth, (unsigned) lpBmih->biHeight);
  260.             GlobalUnlock (dib.hBmi);
  261.             SetDlgItemText (hwnd, IDD_HEADER, szHeader);
  262.  
  263.             bDirty = TRUE;
  264.             EnableWindow (GetDlgItem (hwnd, IDD_SAVE), TRUE);
  265.             InvalidateRect (hwnd, &rectPicture, FALSE);
  266.             return 0;
  267.  
  268.         case IDD_SAVE:
  269.             //
  270.             // Shrink or expand the bitmap and save it to disk.
  271.             //
  272.             if (!GetSaveName (hwnd, szFileName, sizeof (szFileName)))
  273.                 return 0;
  274.  
  275.             if (nSize == 4) {
  276.                 lWidth[4] = (LONG) GetSystemMetrics (SM_CXSCREEN);
  277.                 lHeight[4] = (LONG) GetSystemMetrics (SM_CYSCREEN); 
  278.             }
  279.  
  280.             hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  281.             i = StretchDibAndSave (szFileName, &dib, lWidth[nSize],
  282.                 lHeight[nSize]);
  283.             SetCursor (hCursor);
  284.  
  285.             if (i)
  286.                 MessageBox (hwnd, szError[i], szError[0], MB_OK);
  287.             return 0;
  288.  
  289.         case IDD_640:
  290.         case IDD_800:
  291.         case IDD_1024:
  292.         case IDD_1280:
  293.         case IDD_SCREEN:
  294.             //
  295.             // Process a click of one of the Output Resolution radio buttons.
  296.             //
  297.             CheckRadioButton (hwnd, IDD_640, IDD_SCREEN, wParam);
  298.             nSize = (int) wParam - IDD_640;
  299.             return 0;
  300.  
  301.         case IDCANCEL:
  302.             //
  303.             // Minimize the window when the Esc key is pressed.
  304.             //
  305.             ShowWindow (hwnd, SW_MINIMIZE);
  306.             return 0;
  307.         }
  308.         break;
  309.  
  310.     case WM_QUERYNEWPALETTE:
  311.         //
  312.         // If a bitmap is displayed, realize its palette prior to receiving
  313.         // the input focus and invalidate the area of the window that contains
  314.         // the bitmap image if a color remapping occurred.
  315.         //
  316.         if (bDirty) {
  317.             hdc = GetDC (hwnd);
  318.             SelectPalette (hdc, dib.hPalette, 0);
  319.  
  320.             if (i = RealizePalette (hdc))
  321.                 InvalidateRect (hwnd, &rectPicture, FALSE);
  322.  
  323.             ReleaseDC (hwnd, hdc);
  324.             return i;
  325.         }
  326.         break;
  327.  
  328.     case WM_PALETTECHANGED:
  329.         //
  330.         // If a bitmap is displayed, realize its palette if another window
  331.         // receives the input focus and realizes its own palette.
  332.         //
  333.         if ((wParam != (WPARAM) hwnd) && bDirty) {
  334.             hdc = GetDC (hwnd);
  335.             SelectPalette (hdc, dib.hPalette, 0);
  336.  
  337.             if (RealizePalette (hdc))
  338.                 InvalidateRect (hwnd, &rectPicture, FALSE);
  339.  
  340.             ReleaseDC (hwnd, hdc);
  341.             return 0;
  342.         }
  343.         break;
  344.  
  345.     case WM_SYSCOMMAND:
  346.         //
  347.         // Display the About AllPaper dialog box.
  348.         //
  349.         if (wParam == IDM_ABOUT) {
  350.             lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance);
  351.             DialogBox (hInstance, "AboutBox", hwnd, lpfnAboutDlgProc);
  352.             FreeProcInstance (lpfnAboutDlgProc);
  353.             return 0;
  354.         }
  355.         break;
  356.  
  357.     case WM_CLOSE:
  358.         //
  359.         // Save program settings to ALLPAPER.INI and call DestroyWindow to
  360.         // terminate the program.
  361.         //
  362.         SaveSettings (hwnd);
  363.         DestroyWindow (hwnd);
  364.         return 0;
  365.  
  366.     case WM_ENDSESSION:
  367.         //
  368.         // Save program settings to ALLPAPER.INI before terminating.
  369.         //
  370.         if (wParam)
  371.             SaveSettings (hwnd);
  372.         return 0;
  373.  
  374.     case WM_DESTROY:
  375.         //
  376.         // Free memory and delete GDI objects before terminating.
  377.         //
  378.         DeleteObject (hPatternBrush);
  379.  
  380.         if (bDirty) {
  381.             GlobalFree (dib.hBmi);
  382.             GlobalFree (dib.hBits);
  383.             DeleteObject (dib.hPalette);
  384.         }
  385.  
  386.         PostQuitMessage (0);
  387.         return 0;
  388.     }
  389.     return DefDlgProc (hwnd, message, wParam, lParam);
  390. }
  391.  
  392. /*
  393.  *  GetOpenName obtains an open file name from the user.
  394.  *
  395.  *  Input parameters:
  396.  *
  397.  *    hwnd = Window handle
  398.  *    szFileName = Pointer to file name buffer
  399.  *    nMaxChar = Length of file name buffer
  400.  *
  401.  *  Returns:
  402.  *
  403.  *    TRUE = A valid file name was entered
  404.  *    FALSE = A valid file name was not entered
  405.  */
  406.  
  407. BOOL GetOpenName (HWND hwnd, char *szFileName, int nMaxChar)
  408. {
  409.     static bFirstTime = TRUE;
  410.  
  411.     szFileName[0] = 0x00;
  412.     if (bFirstTime) {
  413.         bFirstTime = FALSE;
  414.         ofn.nFilterIndex = 1;
  415.     }
  416.  
  417.     ofn.lStructSize = sizeof (OPENFILENAME);
  418.     ofn.hwndOwner = hwnd;
  419.     ofn.lpstrFilter = szFilter[0];
  420.     ofn.lpstrCustomFilter = NULL;
  421.     ofn.lpstrFile = szFileName;
  422.     ofn.nMaxFile = nMaxChar;
  423.     ofn.lpstrFileTitle = NULL;
  424.     ofn.lpstrInitialDir = NULL;
  425.     ofn.lpstrTitle = NULL;
  426.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  427.     ofn.lpstrDefExt = NULL;
  428.  
  429.     return (GetOpenFileName (&ofn));
  430. }
  431.  
  432. /*
  433.  *  GetSaveName obtains a save file name from the user.
  434.  *
  435.  *  Input parameters:
  436.  *
  437.  *    hwnd = Window handle
  438.  *    szFileName = Pointer to file name buffer
  439.  *    nMaxChar = Size of file name buffer
  440.  *
  441.  *  Returns:
  442.  *
  443.  *    TRUE = A valid file name was entered
  444.  *    FALSE = A valid file name was not entered
  445.  */
  446.  
  447. BOOL GetSaveName (HWND hwnd, char *szFileName, int nMaxChar)
  448. {
  449.     szFileName[0] = 0x00;
  450.  
  451.     ofn.lStructSize = sizeof (OPENFILENAME);
  452.     ofn.hwndOwner = hwnd;
  453.     ofn.lpstrFilter = szFilter[0];
  454.     ofn.lpstrCustomFilter = NULL;
  455.     ofn.lpstrFile = szFileName;
  456.     ofn.nMaxFile = nMaxChar;
  457.     ofn.lpstrFileTitle = NULL;
  458.     ofn.lpstrInitialDir = NULL;
  459.     ofn.lpstrTitle = NULL;
  460.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOTESTFILECREATE;
  461.     ofn.lpstrDefExt = NULL;
  462.  
  463.     return (GetSaveFileName (&ofn));
  464. }
  465.  
  466. /*
  467.  *  ReadDib reads a DIB from disk and returns handles to:
  468.  *
  469.  *    1. A global memory block containing a BITMAPINFOHEADER structure and,
  470.  *       if applicable, a color table
  471.  *
  472.  *    2. A global memory block containing the bitmap bits
  473.  *
  474.  *    3. A logical palette
  475.  *
  476.  *  Input parameters:
  477.  *
  478.  *    hwnd = Window handle
  479.  *    szFileName = Pointer to file name
  480.  *    pDib = Pointer to uninitialized DIB structure
  481.  *
  482.  *  Returns:
  483.  *
  484.  *    0 = DIB successfully loaded
  485.  *    ERROR_OPENING_FILE = The file was not found or could not be opened
  486.  *    UNSUPPORTED_FORMAT = Unsupported file format (not a DIB file)
  487.  *    COMPRESSED_FILE = Unsupported file format (DIB is compressed) 
  488.  *    ERROR_READING_FILE = Error reading data from the file
  489.  *    NOT_ENOUGH_MEMORY = Global memory allocation failed
  490.  *    END_OF_FILE = End of file encountered unexpectedly
  491.  *
  492.  *  Notes:
  493.  *
  494.  *    OS/2-style DIBs are converted to Windows DIB format (BITMAPCOREINFO
  495.  *    becomes BITMAPINFO).
  496.  *
  497.  *    If the DIB contains more than 256 colors, the palette handle returned
  498.  *    in the DIB structure is that of Windows's default palette.
  499.  *
  500.  *    Currently, this routine does not support compressed DIBs. An attempt to
  501.  *    read a file stored in BI_RLE4 or BI_RLE8 format returns the error code 
  502.  *    COMPRESSED_FILE. 
  503.  */
  504.  
  505. int ReadDib (HWND hwnd, char *szFileName, DIB *pDib)
  506. {
  507.     HFILE hFile;
  508.     BITMAPFILEHEADER Bmfh;
  509.     UINT nBytesToRead, nBytesRead;
  510.     HGLOBAL hBmi, hPal, hBits;
  511.     LPBITMAPINFO lpBmi;
  512.     LPBITMAPINFOHEADER lpBmih;
  513.     LPBITMAPCOREHEADER lpBmch;
  514.     LPBITMAPCOREINFO lpBmci;
  515.     DWORD dwFileType, dwColors, dwBytesRemaining;
  516.     short nWidth, nHeight;
  517.     WORD wPlanes, wBitCount;
  518.     LPLOGPALETTE lpPalette;
  519.     HPALETTE hPalette;
  520.     BYTE __huge *hpbBuffer;
  521.     int i;
  522.  
  523.     //
  524.     //
  525.     // Open the file.
  526.     //
  527.     if ((hFile = _lopen (szFileName, READ)) == HFILE_ERROR)
  528.         return ERROR_OPENING_FILE;
  529.  
  530.     //
  531.     // Read the bitmap file header into memory and check for the "BM"
  532.     // signature in the bfType field.
  533.     //
  534.     Bmfh.bfType = 0;
  535.     nBytesToRead = sizeof (BITMAPFILEHEADER);
  536.     nBytesRead = _lread (hFile, &Bmfh, nBytesToRead);
  537.  
  538.     if (nBytesRead < nBytesToRead) {
  539.         _lclose (hFile);
  540.         return END_OF_FILE;
  541.     }
  542.  
  543.     if (nBytesRead == HFILE_ERROR) {
  544.         _lclose (hFile);
  545.         return ERROR_READING_FILE;
  546.     }
  547.  
  548.     if (Bmfh.bfType != 0x4D42) {
  549.         _lclose (hFile);
  550.         return UNSUPPORTED_FORMAT;
  551.     }
  552.  
  553.     //
  554.     // Read the BITMAPINFOHEADER structure into memory and verify that this
  555.     // is a supported file format by checking the biSize field.
  556.     //
  557.     if ((hBmi = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
  558.         sizeof (BITMAPINFOHEADER) + (256 * sizeof (RGBQUAD)))) == NULL) {
  559.         _lclose (hFile);
  560.         return NOT_ENOUGH_MEMORY;
  561.     }
  562.  
  563.     lpBmi = (LPBITMAPINFO) GlobalLock (hBmi);
  564.     lpBmih = (LPBITMAPINFOHEADER) lpBmi;
  565.  
  566.     nBytesToRead = sizeof (lpBmih->biSize);
  567.     nBytesRead = _lread (hFile, &(lpBmih->biSize), nBytesToRead);
  568.  
  569.     if (nBytesRead < nBytesToRead) {
  570.         GlobalUnlock (hBmi);
  571.         GlobalFree (hBmi);
  572.         _lclose (hFile);
  573.         return END_OF_FILE;
  574.     }
  575.  
  576.     if (nBytesRead == HFILE_ERROR) {
  577.         GlobalUnlock (hBmi);
  578.         GlobalFree (hBmi);
  579.         _lclose (hFile);
  580.         return ERROR_READING_FILE;
  581.     }
  582.  
  583.     dwFileType = lpBmih->biSize;
  584.     if ((dwFileType != 0x28) && (dwFileType != 0x0C)) {
  585.         GlobalUnlock (hBmi);
  586.         GlobalFree (hBmi);
  587.         _lclose (hFile);
  588.         return UNSUPPORTED_FORMAT;
  589.     }           
  590.  
  591.     nBytesToRead = (UINT) (lpBmih->biSize) - sizeof (lpBmih->biSize);
  592.     nBytesRead = _lread (hFile, &(lpBmih->biWidth), nBytesToRead);
  593.  
  594.     if (nBytesRead < nBytesToRead) {
  595.         GlobalUnlock (hBmi);
  596.         GlobalFree (hBmi);
  597.         _lclose (hFile);
  598.         return END_OF_FILE;
  599.     }
  600.  
  601.     if (nBytesRead == HFILE_ERROR) {
  602.         GlobalUnlock (hBmi);
  603.         GlobalFree (hBmi);
  604.         _lclose (hFile);
  605.         return ERROR_READING_FILE;
  606.     }
  607.  
  608.     //
  609.     // If necessary, convert a BITMAPCOREHEADER structure to BITMAPINFOHEADER
  610.     // format. Also set the BITMAPINFOHEADER structure's biSizeImage field.
  611.     //
  612.     if (dwFileType == 0x0C) {
  613.         lpBmch = (LPBITMAPCOREHEADER) lpBmi;
  614.  
  615.         nWidth = lpBmch->bcWidth;
  616.         nHeight = lpBmch->bcHeight;
  617.         wPlanes = lpBmch->bcPlanes;
  618.         wBitCount = lpBmch->bcBitCount;
  619.  
  620.         lpBmih->biSize = sizeof (BITMAPINFOHEADER);
  621.         lpBmih->biWidth = (LONG) nWidth;
  622.         lpBmih->biHeight = (LONG) nHeight;
  623.         lpBmih->biPlanes = wPlanes;
  624.         lpBmih->biBitCount = wBitCount;
  625.         lpBmih->biCompression = BI_RGB;
  626.         lpBmih->biSizeImage = 0;
  627.         lpBmih->biXPelsPerMeter = 0;
  628.         lpBmih->biYPelsPerMeter = 0;
  629.         lpBmih->biClrUsed = 0;
  630.         lpBmih->biClrImportant = 0;
  631.     }
  632.  
  633.     lpBmih->biSizeImage = LINEWIDTH (lpBmih->biWidth * lpBmih->biBitCount) *
  634.         lpBmih->biHeight;
  635.  
  636.     //
  637.     // Make sure that the DIB is not compressed and that it uses 1, 4, 8, or
  638.     // 24 bits per pixel.
  639.     //
  640.     if (lpBmih->biCompression != BI_RGB) {
  641.         GlobalUnlock (hBmi);
  642.         GlobalFree (hBmi);
  643.         _lclose (hFile);
  644.         return COMPRESSED_FILE;
  645.     }
  646.  
  647.     if ((lpBmih->biBitCount != 1) && (lpBmih->biBitCount != 4) &&
  648.         (lpBmih->biBitCount != 8) && (lpBmih->biBitCount != 24)) {
  649.         GlobalUnlock (hBmi);
  650.         GlobalFree (hBmi);
  651.         _lclose (hFile);
  652.         return UNSUPPORTED_FORMAT;
  653.     }           
  654.  
  655.     //
  656.     // Read the color table into memory if the DIB contains a color table,
  657.     // and convert a BITMAPCOREINFO-style color table to BITMAPINFO format if
  658.     // necessary.
  659.     //
  660.     dwColors = ((DWORD) 1) << lpBmih->biBitCount;
  661.  
  662.     if (dwColors <= 256) {
  663.         nBytesToRead = dwColors * ((dwFileType == 0x28) ? sizeof (RGBQUAD) :
  664.             sizeof (RGBTRIPLE));
  665.         nBytesRead = _lread (hFile, &(lpBmi->bmiColors[0]), nBytesToRead);
  666.               
  667.         if (nBytesRead < nBytesToRead) {
  668.             GlobalUnlock (hBmi);
  669.             GlobalFree (hBmi);
  670.             _lclose (hFile);
  671.             return END_OF_FILE;
  672.         }
  673.  
  674.         if (nBytesRead == HFILE_ERROR) {
  675.             GlobalUnlock (hBmi);
  676.             GlobalFree (hBmi);
  677.             _lclose (hFile);
  678.             return ERROR_READING_FILE;
  679.         }
  680.  
  681.         if (dwFileType == 0x0C) {
  682.             lpBmci = (LPBITMAPCOREINFO) ((BYTE FAR *) lpBmi +
  683.                 sizeof (BITMAPINFOHEADER) - sizeof (BITMAPCOREHEADER));
  684.  
  685.             for (i=(int) dwColors - 1; i>0; i--) {
  686.                 lpBmi->bmiColors[i].rgbReserved = 0;
  687.                 lpBmi->bmiColors[i].rgbRed = lpBmci->bmciColors[i].rgbtRed;
  688.                 lpBmi->bmiColors[i].rgbGreen = lpBmci->bmciColors[i].rgbtGreen;
  689.                 lpBmi->bmiColors[i].rgbBlue = lpBmci->bmciColors[i].rgbtBlue;
  690.             }
  691.         }
  692.     }
  693.  
  694.     //
  695.     // If the bitmap contains 256 or fewer colors, create a logical palette
  696.     // for it. If the bitmap contains more than 256 colors, get Windows's
  697.     // default palette handle.
  698.     //
  699.     if (dwColors <= 256) {
  700.         if ((hPal = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
  701.             sizeof (LOGPALETTE) + (min (256, dwColors) *
  702.             sizeof (PALETTEENTRY)))) == NULL) {
  703.             GlobalUnlock (hBmi);
  704.             GlobalFree (hBmi);
  705.             _lclose (hFile);
  706.             return NOT_ENOUGH_MEMORY;
  707.         }
  708.  
  709.         lpPalette = (LPLOGPALETTE) GlobalLock (hPal);
  710.         lpPalette->palVersion = 0x300;
  711.         lpPalette->palNumEntries = (WORD) dwColors;
  712.  
  713.         for (i=0; i<(int) dwColors; i++) {
  714.             lpPalette->palPalEntry[i].peRed = lpBmi->bmiColors[i].rgbRed;
  715.             lpPalette->palPalEntry[i].peGreen = lpBmi->bmiColors[i].rgbGreen;
  716.             lpPalette->palPalEntry[i].peBlue = lpBmi->bmiColors[i].rgbBlue;
  717.             lpPalette->palPalEntry[i].peFlags = NULL;
  718.         }
  719.  
  720.         hPalette = CreatePalette (lpPalette);
  721.         GlobalUnlock (hPal);
  722.         GlobalFree (hPal);
  723.     }
  724.     else
  725.         hPalette = (HPALETTE) GetStockObject (DEFAULT_PALETTE);
  726.  
  727.     //
  728.     // Allocate a global memory block to hold the bitmap bits.
  729.     //
  730.     if ((hBits = GlobalAlloc (GMEM_MOVEABLE, lpBmih->biSizeImage)) == NULL) {
  731.         GlobalUnlock (hBmi);
  732.         GlobalFree (hBmi);
  733.         DeleteObject (hPalette);
  734.         _lclose (hFile);
  735.         return NOT_ENOUGH_MEMORY;
  736.     }
  737.  
  738.     //
  739.     // Read the bitmap bits into memory.
  740.     //
  741.     hpbBuffer = (BYTE __huge *) GlobalLock (hBits);
  742.     dwBytesRemaining = lpBmih->biSizeImage;
  743.     _llseek (hFile, (LONG) Bmfh.bfOffBits, 0);
  744.  
  745.     while (dwBytesRemaining) {
  746.         nBytesToRead = min (IO_BLOCK_SIZE, dwBytesRemaining);
  747.         nBytesRead = _lread (hFile, hpbBuffer, nBytesToRead);
  748.  
  749.         if (nBytesRead < nBytesToRead) {
  750.             MessageBox (hwnd, szWarning[1], szWarning[0], MB_OK);
  751.             break;
  752.         }           
  753.  
  754.         if (nBytesRead == HFILE_ERROR) {
  755.             GlobalUnlock (hBits);
  756.             GlobalFree (hBits);
  757.             GlobalUnlock (hBmi);
  758.             GlobalFree (hBmi);
  759.             DeleteObject (hPalette);
  760.             _lclose (hFile);
  761.             return ERROR_READING_FILE;
  762.         }
  763.         dwBytesRemaining -= nBytesRead;
  764.         hpbBuffer += nBytesRead;
  765.     }
  766.  
  767.     //
  768.     // Clean up, copy handles to the DIB structure, and return.
  769.     //
  770.     GlobalUnlock (hBits);
  771.     GlobalUnlock (hBmi);
  772.     _lclose (hFile);
  773.  
  774.     pDib->hBmi = hBmi;
  775.     pDib->hBits = hBits;
  776.     pDib->hPalette = hPalette;
  777.     return 0;
  778. }
  779.  
  780. /*
  781.  *  StretchDibAndSave shrinks or expands a DIB to the specified dimensions
  782.  *  and saves the resulting image to disk.
  783.  *
  784.  *  Input parameters:
  785.  *
  786.  *    szFileName = Pointer to save file name
  787.  *    pDib = Pointer to initialized DIB structure
  788.  *    lWidth = New bitmap width
  789.  *    lHeight = New bitmap height
  790.  *
  791.  *  Returns:
  792.  *
  793.  *    0 = DIB successfully resized and saved
  794.  *    NOT_ENOUGH_MEMORY = Global memory allocation failed
  795.  *    ERROR_CREATING_FILE = File could not be created
  796.  *    ERROR_WRITING_FILE = Error writing data to file
  797.  *    DISK_FULL = Disk full
  798.  */
  799.  
  800. StretchDibAndSave (char *szFileName, DIB *pDib, LONG lWidth, LONG lHeight)
  801. {
  802.     HFILE hFile;
  803.     HGLOBAL hBmi, hBits;
  804.     BITMAPFILEHEADER Bmfh;
  805.     LPBITMAPINFOHEADER lpBmih;
  806.     BYTE FAR *lpbSrc, FAR *lpbDest;
  807.     BYTE __huge *hpbSrc, __huge *hpbDest, __huge *hpbBuffer;
  808.     UINT nBytesToWrite, nBytesWritten;
  809.     LONG lWidthSrc, lHeightSrc;
  810.     DWORD dwBytesRemaining;
  811.     int nSizeColorTable, i;
  812.  
  813.     //
  814.     // Build a BITMAPINFOHEADER structure and, if applicable, a color table
  815.     // for the new DIB.
  816.     //
  817.     if ((hBmi = GlobalAlloc (GMEM_MOVEABLE, sizeof (BITMAPINFOHEADER) +
  818.         (256 * sizeof (RGBQUAD)))) == NULL)
  819.         return NOT_ENOUGH_MEMORY;
  820.  
  821.     lpBmih = (LPBITMAPINFOHEADER) GlobalLock (hBmi);
  822.     lpbSrc = (BYTE FAR *) GlobalLock (pDib->hBmi);
  823.     lpbDest = (BYTE FAR *) lpBmih;
  824.  
  825.     lWidthSrc = ((LPBITMAPINFOHEADER) lpbSrc)->biWidth;
  826.     lHeightSrc = ((LPBITMAPINFOHEADER) lpbSrc)->biHeight;
  827.  
  828.     for (i=0; i<sizeof (BITMAPINFOHEADER); i++)
  829.         lpbDest[i] = lpbSrc[i];
  830.  
  831.     nSizeColorTable = (lpBmih->biBitCount <= 8) ?
  832.         ((1 << lpBmih->biBitCount) * sizeof (RGBQUAD)): 0;
  833.  
  834.     if (nSizeColorTable) {
  835.         lpbSrc += sizeof (BITMAPINFOHEADER);
  836.         lpbDest += sizeof (BITMAPINFOHEADER);
  837.         for (i=0; i<nSizeColorTable; i++)
  838.             lpbDest[i] = lpbSrc[i];
  839.     }
  840.  
  841.     GlobalUnlock (pDib->hBmi);
  842.  
  843.     lpBmih->biWidth = lWidth;
  844.     lpBmih->biHeight = lHeight;
  845.     lpBmih->biSizeImage = LINEWIDTH (lpBmih->biWidth * lpBmih->biBitCount) *
  846.         lpBmih->biHeight;
  847.     dwBytesRemaining = lpBmih->biSizeImage;
  848.  
  849.     //
  850.     // Allocate a global memory block to hold the bitmap bits and stretch
  851.     // the bits from the source bitmap.
  852.     //
  853.     if ((hBits = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
  854.         lpBmih->biSizeImage)) == NULL) {
  855.         GlobalUnlock (hBmi);
  856.         GlobalFree (hBmi);
  857.         return NOT_ENOUGH_MEMORY;
  858.     }
  859.  
  860.     hpbSrc = (BYTE __huge *) GlobalLock (pDib->hBits);
  861.     hpbDest = (BYTE __huge *) GlobalLock (hBits);
  862.     hpbBuffer = hpbDest;
  863.  
  864.     StretchBits (hpbDest, (int) lWidth, (int) lHeight, hpbSrc,
  865.         (int) lWidthSrc, (int) lHeightSrc, (int) lpBmih->biBitCount);
  866.  
  867.     GlobalUnlock (pDib->hBits);
  868.  
  869.     //
  870.     // Create the output file.
  871.     //
  872.     if ((hFile = _lcreat (szFileName, 0)) == HFILE_ERROR) {
  873.         GlobalUnlock (hBits);
  874.         GlobalFree (hBits);
  875.         GlobalUnlock (hBmi);
  876.         GlobalFree (hBmi);
  877.         return ERROR_CREATING_FILE;
  878.     }
  879.  
  880.     //
  881.     // Build the bitmap file header and write it to disk.
  882.     //
  883.     Bmfh.bfType = 0x4D42;
  884.     Bmfh.bfSize = sizeof (Bmfh) + sizeof (BITMAPINFOHEADER) +
  885.         nSizeColorTable + lpBmih->biSizeImage;
  886.     Bmfh.bfReserved1 = 0;
  887.     Bmfh.bfReserved2 = 0;
  888.     Bmfh.bfOffBits = sizeof (Bmfh) + sizeof (BITMAPINFOHEADER) +
  889.         nSizeColorTable;
  890.  
  891.     nBytesWritten = _lwrite (hFile, &Bmfh, sizeof (Bmfh));
  892.  
  893.     if (nBytesWritten < sizeof (Bmfh)) {
  894.         GlobalUnlock (hBits);
  895.         GlobalFree (hBits);
  896.         GlobalUnlock (hBmi);
  897.         GlobalFree (hBmi);
  898.         _lclose (hFile);
  899.         return DISK_FULL;
  900.     }
  901.  
  902.     if (nBytesWritten == HFILE_ERROR) {
  903.         GlobalUnlock (hBits);
  904.         GlobalFree (hBits);
  905.         GlobalUnlock (hBmi);
  906.         GlobalFree (hBmi);
  907.         _lclose (hFile);
  908.         return ERROR_WRITING_FILE;
  909.     }
  910.  
  911.     //
  912.     // Write the BITMAPINFOHEADER structure and color table to disk.
  913.     //
  914.     nBytesToWrite = sizeof (BITMAPINFOHEADER) + nSizeColorTable;
  915.     nBytesWritten = _lwrite (hFile, lpBmih, nBytesToWrite);
  916.  
  917.     GlobalUnlock (hBmi);
  918.     GlobalFree (hBmi);
  919.  
  920.     if (nBytesWritten < nBytesToWrite) {
  921.         GlobalUnlock (hBits);
  922.         GlobalFree (hBits);
  923.         _lclose (hFile);
  924.         return DISK_FULL;
  925.     }
  926.  
  927.     if (nBytesWritten == HFILE_ERROR) {
  928.         GlobalUnlock (hBits);
  929.         GlobalFree (hBits);
  930.         _lclose (hFile);
  931.         return ERROR_WRITING_FILE;
  932.     }
  933.  
  934.     //
  935.     // Write the bitmap bits to disk.
  936.     //
  937.     while (dwBytesRemaining) {
  938.         nBytesToWrite = min (IO_BLOCK_SIZE, dwBytesRemaining);
  939.         nBytesWritten = _lwrite (hFile, hpbBuffer, nBytesToWrite);
  940.  
  941.         if (nBytesWritten < nBytesToWrite) {
  942.             GlobalUnlock (hBits);
  943.             GlobalFree (hBits);
  944.             _lclose (hFile);
  945.             return DISK_FULL;
  946.         }
  947.  
  948.         if (nBytesWritten == HFILE_ERROR) {
  949.             GlobalUnlock (hBits);
  950.             GlobalFree (hBits);
  951.             _lclose (hFile);
  952.             return ERROR_WRITING_FILE;
  953.         }
  954.         dwBytesRemaining -= nBytesWritten;
  955.         hpbBuffer += nBytesWritten;
  956.     }
  957.  
  958.     //
  959.     // Clean up and return.
  960.     //
  961.     GlobalUnlock (hBits);
  962.     GlobalFree (hBits);
  963.     _lclose (hFile);
  964.     return 0;
  965. }
  966.  
  967. /*
  968.  *  StretchBits shrinks or expands the bits in a buffer representing a
  969.  *  bitmap image.
  970.  *
  971.  *  Input parameters:
  972.  *
  973.  *    hpbDest = Pointer to buffer for destination bitmap
  974.  *    nWidthDest = Width of destination bitmap 
  975.  *    nHeightDest = Height of destination bitmap
  976.  *    hpbSrc = Pointer to buffer for source bitmap
  977.  *    nWidthSrc = Width of source bitmap 
  978.  *    nHeightSrc = Height of source bitmap
  979.  *    nBits = Bits per pixel
  980.  *
  981.  *  Returns:
  982.  *
  983.  *    Nothing
  984.  */
  985.  
  986. void StretchBits (BYTE __huge *hpbDest, int nWidthDest, int nHeightDest,
  987.                   BYTE __huge *hpbSrc, int nWidthSrc, int nHeightSrc,
  988.                   int nBits)
  989. {
  990.     double dRatio;
  991.     DWORD dwIncrement, dwIncrementWidth, dwIncCount;
  992.     UINT nMultiplier, nMultiplierWidth, nOutputRows, i, j;
  993.     UINT nBytesPerLineSrc, nBytesPerLineDest;
  994.  
  995.     //
  996.     // Compute the replication factors for both width and height.
  997.     //
  998.     dRatio = (double) nWidthDest / (double) nWidthSrc;
  999.     nMultiplierWidth = (UINT) floor (dRatio);
  1000.     dwIncrementWidth = (DWORD) ceil ((dRatio - floor (dRatio)) * COUNTER_BASE);
  1001.  
  1002.     dRatio = (double) nHeightDest / (double) nHeightSrc;
  1003.     nMultiplier = (UINT) floor (dRatio);
  1004.     dwIncrement = (DWORD) ceil ((dRatio - floor (dRatio)) * COUNTER_BASE);
  1005.  
  1006.     //
  1007.     // Compute the size (in bytes) of each scan line in both the source and
  1008.     // destination bitmaps.
  1009.     //
  1010.     nBytesPerLineSrc = (UINT) LINEWIDTH ((DWORD) nWidthSrc * (DWORD) nBits);
  1011.     nBytesPerLineDest = (UINT) LINEWIDTH ((DWORD) nWidthDest * (DWORD) nBits);
  1012.  
  1013.     //
  1014.     // Initialize counters.
  1015.     //
  1016.     dwIncCount = 0;
  1017.     nOutputRows = 0;
  1018.  
  1019.     //
  1020.     // Shrink or expand the bits one scan line at a time.
  1021.     //
  1022.     for (i=0; i<nHeightSrc; i++) {
  1023.         if (nMultiplier != 0) {
  1024.             for (j=0; j<nMultiplier; j++) {
  1025.                 StretchScanLine (hpbDest, nWidthDest, hpbSrc, nWidthSrc,
  1026.                     nBits, nMultiplierWidth, dwIncrementWidth);
  1027.                 hpbDest += nBytesPerLineDest;
  1028.                 nOutputRows++;
  1029.             }
  1030.         }
  1031.  
  1032.         dwIncCount += dwIncrement;
  1033.  
  1034.         if ((dwIncCount >= COUNTER_BASE) && (nOutputRows < nHeightDest)) {
  1035.             StretchScanLine (hpbDest, nWidthDest, hpbSrc, nWidthSrc, nBits,
  1036.                 nMultiplierWidth, dwIncrementWidth);
  1037.             hpbDest += nBytesPerLineDest;
  1038.             nOutputRows++;
  1039.             dwIncCount -= COUNTER_BASE;
  1040.         }
  1041.         hpbSrc += nBytesPerLineSrc;
  1042.     }
  1043. }
  1044.  
  1045. /*
  1046.  *  StretchScanLine shrinks or expands the bits in a buffer representing one
  1047.  *  scan line of a bitmap image.
  1048.  *
  1049.  *  Input parameters:
  1050.  *
  1051.  *    hpbDest = Pointer to buffer for destination bitmap
  1052.  *    nWidthDest = Width of destination bitmap 
  1053.  *    hpbSrc = Pointer to buffer for source bitmap
  1054.  *    nWidthSrc = Width of source bitmap
  1055.  *    nBits = Bits per pixel
  1056.  *    nMultiplier = Multiplicative pixel replication factor
  1057.  *    dwIncrement = Incremental pixel replication factor
  1058.  *
  1059.  *  Returns:
  1060.  *
  1061.  *    Nothing
  1062.  */
  1063.  
  1064. void StretchScanLine (BYTE __huge *hpbDest, int nWidthDest,
  1065.                       BYTE __huge *hpbSrc, int nWidthSrc, int nBits,
  1066.                       UINT nMultiplier, DWORD dwIncrement)
  1067. {
  1068.     UINT nOutputPixels, i, j;
  1069.     DWORD dwIncCount, dwBitIndexSrc, dwBitIndexDest;
  1070.  
  1071.     //
  1072.     // Initialize counters.
  1073.     //
  1074.     dwIncCount = 0;
  1075.     nOutputPixels = 0;
  1076.     dwBitIndexSrc = 0;
  1077.     dwBitIndexDest = 0;
  1078.  
  1079.     //
  1080.     // Read through the scan line from left to right, writing pixels to the
  1081.     // destination buffer as appropriate.
  1082.     //
  1083.     for (i=0; i<nWidthSrc; i++) {
  1084.         if (nMultiplier != 0) {
  1085.             for (j=0; j<nMultiplier; j++) {
  1086.                 CopyBits (hpbDest, dwBitIndexDest, hpbSrc, dwBitIndexSrc,
  1087.                     nBits);
  1088.                 dwBitIndexDest += nBits;
  1089.                 nOutputPixels++;
  1090.             }
  1091.         }
  1092.  
  1093.         dwIncCount += dwIncrement;
  1094.  
  1095.         if ((dwIncCount >= COUNTER_BASE) && (nOutputPixels < nWidthDest)) {
  1096.             CopyBits (hpbDest, dwBitIndexDest, hpbSrc, dwBitIndexSrc, nBits);
  1097.             dwBitIndexDest += nBits;
  1098.             nOutputPixels++;
  1099.             dwIncCount -= COUNTER_BASE;
  1100.         }
  1101.         dwBitIndexSrc += nBits;
  1102.     }
  1103. }
  1104.  
  1105. /*
  1106.  *  CopyBits copies the specified number of bits from the source bitmap to
  1107.  *  the destination bitmap.
  1108.  *
  1109.  *  Input parameters:
  1110.  *
  1111.  *    hpbDest = Pointer to buffer for destination bitmap
  1112.  *    nBitIndexDest = Destination bit index
  1113.  *    hpbSrc = Pointer to buffer for source bitmap
  1114.  *    nBitIndexSrc = Source bit index
  1115.  *    nBits = Number of bits to copy
  1116.  *
  1117.  *  Returns:
  1118.  *
  1119.  *    Nothing
  1120.  *
  1121.  *  Notes:
  1122.  *
  1123.  *    For 8- and 24-bit moves, it is valid to assume that the source and
  1124.  *    destination addresses for the move fall on byte boundaries. For 4-bit
  1125.  *    moves, it is valid to assume that the source and destination addresses
  1126.  *    fall on byte or half-byte boundaries. This function handles 1-, 4-, 8-,
  1127.  *    and 24-bit moves exclusively. No error checking is performed to ensure
  1128.  *    that the value passed in the nBits parameter is 1, 4, 8, or 24.
  1129.  */
  1130.  
  1131. void CopyBits (BYTE __huge *hpbDest, DWORD dwBitIndexDest, BYTE __huge *hpbSrc,
  1132.                DWORD dwBitIndexSrc, int nBits)
  1133. {
  1134.     DWORD dwByteIndexSrc, dwByteIndexDest;
  1135.     BYTE byAndMaskSrc, byAndMaskDest, byOrVal;
  1136.  
  1137.     dwByteIndexSrc = dwBitIndexSrc >> 3;
  1138.     dwByteIndexDest = dwBitIndexDest >> 3;
  1139.  
  1140.     switch (nBits) {
  1141.  
  1142.     case 1:
  1143.         byAndMaskSrc = 0x80 >> (dwBitIndexSrc & 0x07);
  1144.         byOrVal = 0x80 >> (dwBitIndexDest & 0x07);
  1145.         byAndMaskDest = ~byOrVal;
  1146.         hpbDest[dwByteIndexDest] &= byAndMaskDest;
  1147.         if (hpbSrc[dwByteIndexSrc] & byAndMaskSrc)
  1148.             hpbDest[dwByteIndexDest] |= byOrVal;
  1149.         break;
  1150.  
  1151.     case 4:
  1152.         byAndMaskDest = ((dwByteIndexDest << 3) == dwBitIndexDest) ?
  1153.             0x0F : 0xF0;
  1154.         byAndMaskSrc = ((dwByteIndexSrc << 3) == dwBitIndexSrc) ?
  1155.             0xF0 : 0x0F;
  1156.         byOrVal = hpbSrc[dwByteIndexSrc] & byAndMaskSrc;
  1157.  
  1158.         if ((byAndMaskSrc == 0xF0) && (byAndMaskDest == 0xF0)) 
  1159.             byOrVal >>= 4;
  1160.         else if ((byAndMaskSrc == 0x0F) && (byAndMaskDest == 0x0F))
  1161.             byOrVal <<= 4;
  1162.  
  1163.         hpbDest[dwByteIndexDest] = (hpbDest[dwByteIndexDest] &
  1164.             byAndMaskDest) | byOrVal;
  1165.         break;
  1166.  
  1167.     case 8:
  1168.         hpbDest[dwByteIndexDest] = hpbSrc[dwByteIndexSrc];
  1169.         break;
  1170.  
  1171.     case 24:
  1172.         hpbDest[dwByteIndexDest] = hpbSrc[dwByteIndexSrc];
  1173.         hpbDest[dwByteIndexDest + 1] = hpbSrc[dwByteIndexSrc + 1];
  1174.         hpbDest[dwByteIndexDest + 2] = hpbSrc[dwByteIndexSrc + 2];
  1175.         break;
  1176.     }
  1177. }
  1178.  
  1179. /*
  1180.  *  InitGroupRect saves the coordinates of the control window in a RECT
  1181.  *  structure, and optionally destroys the control.
  1182.  *
  1183.  *  Input parameters:
  1184.  *
  1185.  *    hwnd = Handle of the control's parent
  1186.  *    nID = Control ID
  1187.  *    rect = Pointer to RECT structure to receive the coordinates
  1188.  *    bDestroy = Flag specifying whether the control should be destroyed
  1189.  *
  1190.  *  Returns:
  1191.  *
  1192.  *    Nothing
  1193.  */
  1194.  
  1195. void InitGroupRect (HWND hwnd, int nID, RECT *rect, BOOL bDestroy)
  1196. {
  1197.     GetWindowRect (GetDlgItem (hwnd, nID), rect);
  1198.     ScreenToClient (hwnd, (POINT FAR *) &rect->left);
  1199.     ScreenToClient (hwnd, (POINT FAR *) &rect->right);
  1200.     if (bDestroy)
  1201.         DestroyWindow (GetDlgItem (hwnd, nID));
  1202. }
  1203.  
  1204. /*
  1205.  *  DrawGroupRect draws a recessed group rectangle at the specified location.
  1206.  *
  1207.  *  Input parameters:
  1208.  *
  1209.  *    hdc = Device context handle
  1210.  *    rect = Pointer to RECT structure containing the rectangle's coordinates
  1211.  *
  1212.  *  Returns:
  1213.  *
  1214.  *    Nothing
  1215.  */
  1216.  
  1217. void DrawGroupRect (HDC hdc, RECT *rect)
  1218. {
  1219.     HPEN hPen;
  1220.  
  1221.     FillRect (hdc, rect, GetStockObject (LTGRAY_BRUSH)); 
  1222.     hPen = CreatePen (PS_SOLID, 1, RGB (128, 128, 128));
  1223.     SelectObject (hdc, hPen);
  1224.     MoveTo (hdc, rect->left, rect->bottom - 1);
  1225.     LineTo (hdc, rect->left, rect->top);
  1226.     LineTo (hdc, rect->right, rect->top);
  1227.     DeleteObject (SelectObject (hdc, GetStockObject (WHITE_PEN)));
  1228.     MoveTo (hdc, rect->right - 1, rect->top + 1);
  1229.     LineTo (hdc, rect->right - 1, rect->bottom - 1);
  1230.     LineTo (hdc, rect->left, rect->bottom - 1);
  1231. }
  1232.  
  1233. /*
  1234.  *  PositionWindow positions the window on the screen using the
  1235.  *  WindowPos entry stored in ALLPAPER.INI. If ALLPAPER.INI does not exist,
  1236.  *  if it does exist but does not contain a WindowPos entry, or if WindowPos
  1237.  *  specifies a position that is off (or nearly off) the screen,
  1238.  *  PositionWindows centers the window on the screen.
  1239.  *
  1240.  *  Input parameters:
  1241.  *
  1242.  *    hwnd = Window handle
  1243.  *
  1244.  *  Returns:
  1245.  *
  1246.  *    Nothing
  1247.  */
  1248.  
  1249. void PositionWindow (HWND hwnd)
  1250. {
  1251.     char szBuffer[32];
  1252.     static char szDefString[] = "WindowPos=32767,32767";
  1253.     int cxWindowPos, cyWindowPos, cxScreenSize, cyScreenSize;
  1254.     RECT rect;
  1255.  
  1256.     GetPrivateProfileString (szSection, szEntry[0], szDefString, szBuffer,
  1257.         sizeof (szBuffer), szIniFile);
  1258.     sscanf (szBuffer, "%u,%u", &cxWindowPos, &cyWindowPos);
  1259.  
  1260.     cxScreenSize = GetSystemMetrics (SM_CXSCREEN);
  1261.     cyScreenSize = GetSystemMetrics (SM_CYSCREEN);
  1262.  
  1263.     if ((cxWindowPos > (cxScreenSize - 32)) ||
  1264.         (cyWindowPos > (cyScreenSize - 32))) {
  1265.         GetWindowRect (hwnd, &rect);
  1266.         cxWindowPos = (cxScreenSize - (rect.right - rect.left)) >> 1;
  1267.         cyWindowPos = (cyScreenSize - (rect.bottom - rect.top)) >> 1;
  1268.     }
  1269.  
  1270.     SetWindowPos (hwnd, 0, cxWindowPos, cyWindowPos, 0, 0,
  1271.         SWP_NOSIZE | SWP_NOZORDER);
  1272. }
  1273.  
  1274. /*
  1275.  *  InitProgram initializes the program.
  1276.  *
  1277.  *  Input parameters:
  1278.  *
  1279.  *    hwnd = Window handle
  1280.  *
  1281.  *  Returns:
  1282.  *
  1283.  *    Nothing
  1284.  */
  1285.  
  1286. void InitProgram (HWND hwnd)
  1287. {
  1288.     int cxWindowPos, cyWindowPos;
  1289.     char szBuffer[32];
  1290.     RECT rect;
  1291.  
  1292.     //
  1293.     // Initialize group rectangle coordinates.
  1294.     //
  1295.     InitGroupRect (hwnd, IDD_RECT1, &rectFrame, TRUE);
  1296.     InitGroupRect (hwnd, IDD_RECT2, &rectControls, TRUE);
  1297.     CopyRect (&rectPicture, &rectFrame);
  1298.     InflateRect (&rectPicture, -8, -8);
  1299.  
  1300.     //
  1301.     // Set the default output resolution.
  1302.     //
  1303.     nSize = min (GetPrivateProfileInt (szSection, szEntry[1], 4, szIniFile),
  1304.         4);
  1305.     CheckRadioButton (hwnd, IDD_640, IDD_SCREEN, IDD_640 + nSize);
  1306. }
  1307.  
  1308. /*
  1309.  *  SaveSettings saves program settings to ALLPAPER.INI.
  1310.  *
  1311.  *  Input parameters:
  1312.  *
  1313.  *    hwnd = Window handle
  1314.  *
  1315.  *  Returns:
  1316.  *
  1317.  *    Nothing
  1318.  */
  1319.  
  1320. void SaveSettings (HWND hwnd)
  1321. {
  1322.     WINDOWPLACEMENT wp;
  1323.     char szBuffer[32];
  1324.  
  1325.     wp.length = sizeof (wp);
  1326.     GetWindowPlacement (hwnd, &wp);
  1327.     wsprintf (szBuffer, "%u,%u", (wp.rcNormalPosition).left,
  1328.         (wp.rcNormalPosition).top);
  1329.     WritePrivateProfileString (szSection, szEntry[0], szBuffer, szIniFile);
  1330.  
  1331.     WritePrivateProfileString (szSection, szEntry[1],
  1332.         _itoa (nSize, szBuffer, 10), szIniFile);
  1333. }
  1334.  
  1335. /*
  1336.  *  CenterDialog centers a dialog box window (or any window, for that matter)
  1337.  *  on the screen.
  1338.  *
  1339.  *  Input parameters:
  1340.  *
  1341.  *    hwnd = Window handle
  1342.  *
  1343.  *  Returns:
  1344.  *
  1345.  *    Nothing
  1346.  */
  1347.  
  1348. void CenterDialog (HWND hwnd)
  1349. {
  1350.     RECT rect;
  1351.  
  1352.     GetWindowRect (hwnd, &rect);
  1353.     SetWindowPos (hwnd, 0,
  1354.         (GetSystemMetrics (SM_CXSCREEN) - (rect.right - rect.left)) >> 1,
  1355.         (GetSystemMetrics (SM_CYSCREEN) - (rect.bottom - rect.top)) >> 1,
  1356.         0, 0, SWP_NOSIZE | SWP_NOZORDER);
  1357. }
  1358.  
  1359. /*
  1360.  *  AboutDlgProc processes messages to the About AllPaper dialog box.
  1361.  */
  1362.  
  1363. BOOL FAR PASCAL AboutDlgProc (HWND hwnd, WORD message, WORD wParam,
  1364.                               LONG lParam)
  1365. {
  1366.     static HPEN hPen;
  1367.     static RECT rectFrame;
  1368.     static HFONT hDlgFont;
  1369.     PAINTSTRUCT ps;
  1370.     LOGFONT lf;
  1371.     RECT rect;
  1372.     HDC hdc;
  1373.  
  1374.     switch (message) {
  1375.  
  1376.     case WM_INITDIALOG:
  1377.         //
  1378.         // Initialize and create GDI objects.
  1379.         //
  1380.         InitGroupRect (hwnd, IDD_FRAME, &rectFrame, TRUE);
  1381.  
  1382.         if (IsIconic (GetWindow (hwnd, GW_OWNER)))
  1383.             CenterDialog (hwnd);
  1384.  
  1385.         GetObject ((HFONT) SendMessage (hwnd, WM_GETFONT, 0, 0L),
  1386.             sizeof (LOGFONT), &lf);
  1387.         lstrcpy (lf.lfFaceName, "Arial");
  1388.         lf.lfHeight *= 3;
  1389.         lf.lfWidth *= 3;
  1390.         lf.lfItalic = 1;
  1391.         lf.lfOutPrecision = OUT_TT_PRECIS;
  1392.         if ((hDlgFont = CreateFontIndirect ((LPLOGFONT) &lf)) != NULL)
  1393.             SendDlgItemMessage (hwnd, IDD_TITLE, WM_SETFONT, hDlgFont, 0L);
  1394.  
  1395.         hPen = CreatePen (PS_SOLID, 1, RGB (128, 128, 128));
  1396.         return TRUE;
  1397.  
  1398.     case WM_CTLCOLOR:
  1399.         //
  1400.         // Paint all control backgrounds light gray. Also change the title
  1401.         // color to bright red.
  1402.         //
  1403.         SetBkColor ((HDC) wParam, RGB (192, 192, 192));
  1404.         if (GetDlgCtrlID (LOWORD (lParam)) == IDD_TITLE)
  1405.             SetTextColor ((HDC) wParam, RGB (255, 0, 0));
  1406.         return GetStockObject (LTGRAY_BRUSH);
  1407.  
  1408.     case WM_ERASEBKGND:
  1409.         //
  1410.         // Paint the window background light gray.
  1411.         //
  1412.         GetClientRect (hwnd, &rect);
  1413.         FillRect ((HDC) wParam, &rect, GetStockObject (LTGRAY_BRUSH));
  1414.         return TRUE;
  1415.  
  1416.     case WM_PAINT:
  1417.         //
  1418.         // Draw the rectangle surrounding the dialog box text.
  1419.         //
  1420.         hdc = BeginPaint (hwnd, &ps);
  1421.  
  1422.         SelectObject (hdc, hPen);
  1423.         SelectObject (hdc, GetStockObject (NULL_BRUSH));
  1424.         Rectangle (hdc, rectFrame.left, rectFrame.top,
  1425.             rectFrame.right, rectFrame.bottom);
  1426.  
  1427.         SelectObject (hdc, GetStockObject (WHITE_PEN));
  1428.         Rectangle (hdc, rectFrame.left + 1, rectFrame.top + 1,
  1429.             rectFrame.right + 1, rectFrame.bottom + 1);
  1430.  
  1431.         EndPaint (hwnd, &ps);
  1432.         return TRUE;
  1433.  
  1434.     case WM_COMMAND:
  1435.         //
  1436.         // Dismiss the dialog box in response to an IDOK or IDCANCEL message.
  1437.         //
  1438.         switch (wParam) {
  1439.  
  1440.         case IDOK:
  1441.         case IDCANCEL:
  1442.             EndDialog (hwnd, 0);
  1443.             return TRUE;
  1444.         }
  1445.         break;
  1446.  
  1447.     case WM_DESTROY:
  1448.         //
  1449.         // Delete GDI objects.
  1450.         //
  1451.         if (hDlgFont != NULL)
  1452.             DeleteObject (hDlgFont);
  1453.         DeleteObject (hPen);
  1454.         return TRUE;
  1455.     }
  1456.     return FALSE;
  1457. }
  1458.